from flask import request, current_app, jsonify
from sqlalchemy import desc

from library.api.db import db
from library.api.exceptions import SaveObjectException, CannotFindObjectException
from library.api.transfer import transfer2json, slicejson, transfer2jsonwithoutset
from library.trpc import Trpc
from apps.auth.models.users import User, UserBindProject
from apps.project.models.project import Project
from apps.project.business.zentao import ZenTaoBusiness
from apps.interface.business.interfaceapimsg import InterfaceApiMsgBusiness
from apps.interface.business.interfacestatistics import InterfaceStatistics
from apps.interface.business.interfacestatistics import InterfaceStatistics


class ProjectBusiness(object):
    user_trpc = Trpc('auth')
    
    @classmethod
    def _query(cls):
        return Project.query.outerjoin(
            UserBindProject, UserBindProject.project_id == Project.id).outerjoin(
            User, User.id == UserBindProject.user_id).add_columns(
            Project.id.label('id'),
            Project.name.label('name'),
            Project.description.label('description'),
            Project.weight.label('weight'),
            Project.status.label('status'),
            Project.logo.label('logo'),
            User.id.label('user_id'),
            User.nickname.label('nickname'),
        )
    
    @classmethod
    @slicejson(['user|id|nickname|user_id|nickname'])
    @transfer2jsonwithoutset('?id|!name|!description|!status|!weight|!logo|@user_id|@nickname')
    def query_all_json(cls):
        userid = request.args.get('userid')
        ret = cls._query().filter(Project.status == Project.ACTIVE)
        if userid:
            ret = ret.filter(UserBindProject.user_id == userid)
        ret = ret.order_by(
            desc(Project.weight)).order_by(Project.id).all()
        
        return ret
    
    @classmethod
    @slicejson(['user|id|nickname|user_id|nickname'])
    @transfer2json('?id|!name|!description|!status|!weight|!logo|@user_id|@nickname')
    def query_json_by_id(cls, id):
        return cls._query().filter(Project.id == id,
                                   Project.status == Project.ACTIVE).order_by(
            desc(Project.weight)).all()
    
    @classmethod
    def create_new_project(cls, name, zt_product, description, logo):
        ret = Project.query.filter_by(name=name, status=Project.ACTIVE).first()
        if ret:
            raise SaveObjectException('存在相同名称的项目')
        
        p = Project(
            name=name,
            zt_product=zt_product,
            description=description,
            logo=logo,
        )
        db.session.add(p)
        db.session.commit()
        return 0, None
    
    @classmethod
    def modify(cls, id, name, description, weight, logo):
        ret = Project.query.filter_by(name=name,
                                      status=Project.ACTIVE).filter(Project.id != id).first()
        if ret:
            raise SaveObjectException('存在相同名称的项目')
        
        project = Project.query.get(id)
        if not project:
            raise CannotFindObjectException
        
        if project.status == Project.ACTIVE:
            try:
                project.name = name
                project.description = description
                project.weight = weight
                project.logo = logo
                db.session.add(project)
                db.session.commit()
                return 0, None
            except Exception as e:
                db.session.rollback()
                current_app.logger.error(str(e))
                return 102, str(e)
        else:
            return 101, "The Project's Status is DISABLE!"
    
    @classmethod
    def close_project(cls, id):
        project = Project.query.get(id)
        project.status = Project.DISABLE
        db.session.add(project)
        db.session.commit()
        return 0
    
    @classmethod
    def bind_users(cls, pid, userids):
        try:
            [db.session.delete(item) for item in
             UserBindProject.query.filter_by(project_id=pid).all()]
            [db.session.add(UserBindProject(user_id=uid, project_id=pid)) for uid in userids]
            db.session.commit()
            return 0, None
        except Exception as e:
            current_app.logger.error(str(e))
            return 102, str(e)
    
    @classmethod
    def detach_users(cls, pid, userids):
        try:
            [db.session.delete(item) for item in
             UserBindProject.query.filter_by(project_id=pid, user_id=userids).all()]
            db.session.commit()
            return 0, None
        except Exception as e:
            current_app.logger.error(str(e))
            return 102, str(e)
    
    @classmethod
    def add_users(cls, pid, userids):
        try:
            [db.session.add(UserBindProject(user_id=uid, project_id=pid)) for uid in userids]
            db.session.commit()
            return 0, None
        except Exception as e:
            current_app.logger.error(str(e))
            return 102, str(e)
    
    @classmethod
    def detach_users_all(cls, userids):
        try:
            [db.session.delete(item) for item in
             UserBindProject.query.filter_by(user_id=userids).all()]
            db.session.commit()
            return 0, None
        except Exception as e:
            current_app.logger.error(str(e))
            return 102, str(e)
    
    @classmethod
    def index(cls, id):
        start_time = request.args.get('start_time')
        end_time = request.args.get('end_time')
        project_id = id
        project = Project.query.filter_by(id=project_id).first()
        login_response = ZenTaoBusiness.zt_login()
        # ZenTaoBusiness()
        # login_response = ZenTaoBusiness().zt_new_login()
        bug_all = ZenTaoBusiness.zt_bug(project.zt_product, login_response['id'], 'all')
        bug_unclosed = ZenTaoBusiness.zt_bug(project.zt_product, login_response['id'], 'unclosed')
        bug_wait_closed = ZenTaoBusiness.zt_bug(project.zt_product, login_response['id'],
                                                'toclosed')
        times = cls.judge_start_end_time()
        service_case_ret = InterfaceStatistics.get_service_case_total(project_id, times[0],
                                                                          times[1])
        user_case_ret = InterfaceStatistics.get_user_case_total(project_id, times[0], times[1])
        detail = [
            dict(
                requirement_sum=0,
                issue_sum=bug_all['size'],
                task_sum=0,
                requirement_info=[],
                issue_info=[
                    {
                        "count": bug_all['size'],
                        "open": bug_unclosed['size'],
                        "rank": 72,
                        "version_id": project_id,
                        "version_title": bug_all['name']
                    }
                ],
                task_info=[],
                issue_status=[
                    {
                        "count": bug_wait_closed['size'],
                        "handle_status": 1
                    }
                ],
                servcie_case_detail=service_case_ret,
                user_case_detail=user_case_ret,
                taskcase_sum=0,
                tester_data=[],
                create_issue_count=0,
                finish_issue_count=0
            )
        ]
        return detail
    
    @classmethod
    def get_url(cls, all_project_id):
        """
        根据all_project_id 获取图片
        :param all_project_id:
        :return: url
        """
        if not all_project_id:
            return jsonify({'msg': 'all_project_id is not null', 'status': 0})
        project = Project.query.filter_by(id=all_project_id,
                                          status=0).first()
        if not project:
            return jsonify({'msg': 'project is not null', 'status': 0})
        url = project.logo
        return url
    
    @classmethod
    def find_service_interface_total(cls, all_project_id):
        """
        根据all_project_id和时间获取api_total,case_total
        :param all_project_id:
        :return: [{'api':12,'case':2,'project_name':1}]
        """
        try:
            if not all_project_id:
                return 0, {'msg': 'all_project_id is not null'}
            times = cls.judge_start_end_time()
            if times is None:
                return 304, []
            ret = InterfaceStatistics.get_service_case_total(all_project_id, times[0], times[1])
            return 0, ret
        except Exception as error:
            current_app.logger.info('error: {}'.format(str(error)))
            return 500, []
    
    @classmethod
    def find_user_project_interface_total(cls, all_project_id):
        """
        根据all_project_id和时间获取api_total,case_total
        :param all_project_id:
        :return: [{'api':12,'case':2,'张三':1}]
        """
        try:
            if not all_project_id:
                return {'msg': 'all_project_id is not null'}
            times = cls.judge_start_end_time()
            if times is None:
                return 304, []
            ret = InterfaceStatistics.get_user_case_total(all_project_id, times[0], times[1])
            return 0, ret
        
        except Exception as error:
            current_app.logger.info('error: {}'.format(str(error)))
            return 500, []
    
    @classmethod
    def find_all_user_interface_total(cls):
        """
        根据all_project_id和时间获取api_total,case_total
        :return: [{'api':12,'case':2,'张三':1}]
        """
        try:
            times = cls.judge_start_end_time()
            if times is None:
                return 304, []
            ret = InterfaceStatistics.get_all_user_case_total(times[0], times[1])
            return 0, ret
        except Exception as error:
            current_app.logger.info('error: {}'.format(str(error)))
            return 0, []
    
    @classmethod
    def judge_start_end_time(cls):
        """
        判断开始、结束时间
        :return: [start_time, end_time]
        """
        start_time = request.args.get('start_time')
        end_time = request.args.get('end_time')
        
        if not start_time or not end_time:
            return None
        
        # 处理结束时间
        end_time = '{} 23:59:59'.format(end_time)
        return [start_time, end_time]
